/****************************************************
	文件：EngineMgr.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/7/12 13:20:29
	功能：引擎Mgr
*****************************************************/

using System;
using System.Collections.Generic;
using UnityEngine;

namespace HTSpider
{
    public class EngineMgr : Singleton<EngineMgr>
    {
        private Logger mLogger;
        private DownloadMgr mDownloadMgr;
        private ItemPipelineMgr mItemPiplineMgr;
        private ScheduleMgr mScheduleMgr;
        private SpiderMgr mSpiderMgr;
        /// <summary>
        /// Request 的回调队列
        /// </summary>
        private Queue<KeyValuePair<Action<Rsp>, Rsp>> mDoReqCallBackQue;
        private static readonly object mDoReqCallBackQueLock = new object();

        #region 生命周期
        public void Init(Action<object> onLog, Action<object> onWarning, Action<object> onError)
        {
            mLogger = new Logger(onLog, onWarning, onError);
            Logger.Log("Logger init done.");
            mDownloadMgr = DownloadMgr.Instance;
            mDownloadMgr.Init();
            Logger.Log("DownloadMgr init done.");
            mItemPiplineMgr = ItemPipelineMgr.Instance;
            mItemPiplineMgr.Init();
            Logger.Log("ItemPipelineMgr init done.");
            mScheduleMgr = ScheduleMgr.Instance;
            mScheduleMgr.Init();
            Logger.Log("ScheduleMgr init done.");
            mSpiderMgr = SpiderMgr.Instance;
            mSpiderMgr.Init();
            Logger.Log("SpiderMgr init done.");

            mDoReqCallBackQue = new Queue<KeyValuePair<Action<Rsp>, Rsp>>();

            Logger.Log("EngineMgr init done.");
        }
        public void Tick()
        {
            mScheduleMgr.Tick();
            //执行回调队列
            while (mDoReqCallBackQue.Count > 0)
            {
                lock (mDoReqCallBackQueLock)
                {
                    KeyValuePair<Action<Rsp>, Rsp> pair = mDoReqCallBackQue.Dequeue();
                    pair.Key?.Invoke(pair.Value);
                }
            }
        }
        public void OnDestroy()
        {
            mLogger.OnDestroy();
            mLogger = null;
        }
        #endregion

        public void AddReq(Req req)
        {
            mScheduleMgr.AddReq(req);
        }
        public void DoReq(Req req, Action<Rsp> cb = null)
        {
            if (req == null)
            {
                Logger.Error("DoReq Error ! req is null.");
                return;
            }
            Rsp rsp = new Rsp
            {
                Url = req.Url,
                Encoding = req.Encoding,
                Request = req,
            };
            rsp.Content = mDownloadMgr.Get(req.Url, req.Encoding);
            rsp.Time = DateTime.Now;
            rsp.CostTime = (rsp.Time.TimeOfDay - req.Time.TimeOfDay).Milliseconds;
            mSpiderMgr.AddRsp(rsp);
            lock (mDoReqCallBackQueLock)
            {
                mDoReqCallBackQue.Enqueue(new KeyValuePair<Action<Rsp>, Rsp>(cb, rsp));
            }
        }
    }
}
